#ifndef _FACTORY_H_
#define _FACTORY_H_
#include "common/singleton.h"
#if (_MSC_VER >= 1510) && (_MSC_FULL_VER >= 150030729) &&  !defined( _USE_BOOST )
#include <functional>
using namespace std;
#if (_MSC_VER >= 1600)
using namespace std::placeholders;
#else
using namespace std::tr1;
using namespace std::tr1::placeholders;
#endif
#else
#include "boost\function.hpp"
#include "boost\bind.hpp"
using namespace boost;
#endif

namespace XGC
{
	namespace common
	{
		#define FACTORY_REPEAT_COUNT 10
		struct factory_empty_type
		{

		};

		template< typename ret >
		struct factory_impl;

		#define XGC_FACTORY_PARAM_TYPEDEF_REPEAT(X) \
		typedef factory_empty_type Param##N;\

		struct factory_impl_base
		{
			typedef factory_empty_type Ret;
			XGC_MAIN_REPEAT_Z( FACTORY_REPEAT_COUNT, XGC_FACTORY_PARAM_TYPEDEF_REPEAT )
		};
		#undef XGC_FACTORY_PARAM_TYPEDEF_REPEAT

		#define XGC_FACTOR_IMPL_BODY_REPEAT(X)\
		typedef typename param_##N Param##N;\

		#define XGC_FACTOR_IMPL_REPEAT(X)\
		template< class ret XGC_COMMA_IF( N ) XGC_ENUM_D( N, class param_ ) >\
		struct factory_impl< ret(XGC_ENUM_D(N, param_)) >: public factory_impl_base\
		{
			typedef ret Ret;\
			XGC_REPEAT( N, XGC_FACTORY_IMPL_BODY_REPEAT )\
		};\

		XGC_MAIN_REPEAT_Z( FACTORY_REPEAT_COUNT, XGC_FACTOR_IMPL_REPEAT )
		#undef XGC_FACTOR_IMPL_REPEAT
		#undef XGC_FACTOR_IMPL_BODY_REPEAT

		template < typename abstract_ret, typename id_type, typename creator_type >
		class factory
		{
		friend struct CreateUsingNew< factory >
		private:
			factory(){}
			~factory(){}

		private:
			typedef function< creator_type > creator;
			typedef factory_impl< creator_type > param_impl;
			typedef std::map< id_type, creator > id_to_creator;

			id_to_creator creator_map;
		public:
			xgc_void register_creator( id_type id, creator fn )
			{
				id_to_creator[id] = fn;
			}

			#define XGC_FACTORY_CREATOR_REPEAT(X)\
			abstract_ret create_object( id_type id, XGC_COMMA_IF(N), XGC_PARAM_D(N, typename param_impl::Param, P) )const\
			{\
				id_to_creator::const_iterator citor = creator_map.find( id );\
				if( citor != creator_map.end() )\
					return citor->second( XGC_ENUM_D(N,P) );\
				return xgc_nullptr;\
			}\

			XGC_MAIN_REPEAT_Z( FACTORY_REPEAT_COUNT, XGC_FACTORY_CREATOR_REPEAT )
			#undef XGC_FACTORY_CREATOR_REPEAT
		};

		template< typename abstract_ret, typename id_type, typename creator_type >
		struct FactorySingleton : public SingletonHolder< factor< abstract_ret, id_type, creator_type >, CreateUsingNew >
		{

		};
	}
}
#endif // _FACTORY_H_